#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import platform
import sys

from oracle import logger
from common.cleaner import clear
from common.common import exter_attack, output_result_file
from common.common_models import ActionResult
from common.const import SysData, ExecuteResultEnum
from common.parse_parafile import add_env_param, get_env_variable, ParamFileUtil

from oracle.common.constants import ErrorCode, EnvVariableKeys
from oracle.services.threshold_check.check_archive_area import OracleCheckArchiveAreaService
from oracle.services.backup.oracle_backup_service import OracleBackupService
from oracle.services.resource.oracle_resource_service import OracleResourceService
from oracle.services.restore.restore import OracleRestore
from oracle.services.livemount.livemount import OracleLiveMount
from oracle.services.instant_restore.instant_restore import OracleInstRestore


def add_run_user_pwd_to_env(pid, param):
    if param == "dbInfos":
        run_user_pwd = get_env_variable(f"dbInfos_0_runUserPwd_{pid}")
    else:
        run_user_pwd = get_env_variable(f"{param}_auth_extendInfo_runUserPwd_{pid}")
    if not run_user_pwd:
        if platform.system().lower() == "windows":
            file_content = ParamFileUtil.parse_param_windows_file(pid, False)
        else:
            file_content = ParamFileUtil.parse_param_file(pid, False)

        if param == 'job_targetObject':
            run_user_pwd = (
                file_content.get('job', {}).get('targetObject', {}).get('auth', {}).get('extendInfo', {}).get(
                    'runUserInfo', "[]"))
        elif param == 'job_protectObject':
            run_user_pwd = (
                file_content.get('job', {}).get('protectObject', {}).get('auth', {}).get('extendInfo', {}).get(
                    'runUserInfo', "[]"))
        else:
            run_user_pwd = file_content.get('application', {}).get('auth', {}).get('extendInfo',
                                                                                   {}).get('runUserInfo', "[]")

    add_env_param(EnvVariableKeys.run_user_pwd, run_user_pwd)


class OracleApi:

    @staticmethod
    @exter_attack
    def check_application(pid, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "application")
        OracleResourceService.check_application(pid)

    @staticmethod
    @exter_attack
    def list_application(pid, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "application")
        OracleResourceService.list_application(pid)

    @staticmethod
    @exter_attack
    def list_application_v2(pid, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "application")
        OracleResourceService.list_application_v2(pid)

    @staticmethod
    @exter_attack
    def query_cluster(pid, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "application")
        OracleResourceService.query_cluster(pid)

    @staticmethod
    @exter_attack
    def check_archive_area(pid, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "dbInfos")
        OracleCheckArchiveAreaService.check_archive_area(pid)

    @staticmethod
    @exter_attack
    def remove_protect(pid, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "application")
        OracleResourceService.clean_env_when_remove_resource(pid)

    @staticmethod
    @exter_attack
    def allow_backup_in_local_node(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        return OracleBackupService(pid, job_id, sub_job_id).allow_backup_in_local_node()

    @staticmethod
    @exter_attack
    def query_job_permission(pid, job_id, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        return OracleBackupService(pid, job_id).query_job_permission()

    @staticmethod
    @exter_attack
    def check_backup_job_type(pid, job_id, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        return OracleBackupService(pid, job_id).check_backup_job_type()

    @staticmethod
    @exter_attack
    def backup_prerequisite(pid, job_id, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        try:
            OracleBackupService(pid, job_id).backup_prerequisite()
        except Exception as exception:
            logger.error(f'Failed to execute backup_prerequisite, exception:{exception}, pid:{pid}, job_id:{job_id}.',
                         exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))
            raise Exception('Failed to execute backup_prerequisite.') from exception

    @staticmethod
    @exter_attack
    def backup_prerequisite_progress(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        return OracleBackupService(pid, job_id, sub_job_id).backup_prerequisite_progress()

    @staticmethod
    @exter_attack
    def backup(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id, sub_job_id).backup()

    @staticmethod
    @exter_attack
    def query_scan_repositories(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id, sub_job_id).query_scan_repositories()

    @staticmethod
    @exter_attack
    def gen_sub_job(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id, sub_job_id).gen_sub_job()

    @staticmethod
    @exter_attack
    def backup_progress(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id, sub_job_id).backup_progress()

    @staticmethod
    @exter_attack
    def backup_post_job(pid, job_id, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id).backup_post_job()

    @staticmethod
    @exter_attack
    def backup_post_job_progress(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id, sub_job_id).backup_post_job_progress()

    @staticmethod
    @exter_attack
    def abort_job(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id, sub_job_id).abort_job()

    @staticmethod
    @exter_attack
    def report_abort_job_progress(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_protectObject")
        OracleBackupService(pid, job_id, sub_job_id).report_abort_job_progress()

    @staticmethod
    @exter_attack
    def allow_restore_in_local_node(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).allow_restore_in_local_node()
        except Exception as exception:
            logger.error(
                f'Failed to execute allow_restore_in_local_node, exception:{exception}, pid:{pid}, job_id:{job_id}.',
                exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))
            raise Exception('Failed to execute allow_restore_in_local_node.') from exception

    @staticmethod
    @exter_attack
    def restore_prerequisite(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).restore_prerequisite()
        except Exception as exception:
            logger.error(f'Failed to execute restore_prerequisite, exception:{exception}, pid:{pid}, job_id:{job_id}.',
                         exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))
            raise Exception('Failed to execute restore_prerequisite.') from exception

    @staticmethod
    @exter_attack
    def restore_prerequisite_progress(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).restore_prerequisite_progress()
        except Exception as exception:
            logger.error(f'Failed to execute restore_prerequisite_progress, exception:{exception}, pid:{pid}, '
                         f'job_id:{job_id}.', exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))

    @staticmethod
    @exter_attack
    def restore_gen_sub_job(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).restore_gen_sub_job()
        except Exception as exception:
            logger.error(
                f'Generate restore sub job failed, exception:{exception}, job_id:{job_id}, sub_job_id:{sub_job_id}.')
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))
            raise Exception('Failed to execute restore_gen_sub_job.') from exception

    @staticmethod
    @exter_attack
    def restore(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).restore()
        except Exception as exception:
            logger.error(f'Run oracle restore failed, e:{exception}, job_id:{job_id}, sub_job_id:{sub_job_id}.',
                         exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))
            raise Exception('Failed to execute restore.') from exception

    @staticmethod
    @exter_attack
    def restore_progress(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).restore_progress()
        except Exception as exception:
            logger.error(
                f'Query oracle restore progress failed, e:{exception}, job_id:{job_id}, sub_job_id:{sub_job_id}.',
                exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))

    @staticmethod
    @exter_attack
    def restore_post_job(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).restore_post_job()
        except Exception as exception:
            logger.error(f'Restore post job failed, exception:{exception}, job_id:{job_id}, sub_job_id:{sub_job_id}.',
                         exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))
            raise Exception('Failed to execute restore_post_job.') from exception

    @staticmethod
    @exter_attack
    def restore_post_job_progress(pid, job_id, sub_job_id):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "job_targetObject")
        try:
            OracleRestore(pid, job_id, sub_job_id).restore_post_job_progress()
        except Exception as exception:
            logger.error(
                f'Query restore post job progress failed, e:{exception}, job_id:{job_id}, sub_job_id:{sub_job_id}.',
                exc_info=True)
            output_result_file(pid, ActionResult(code=ExecuteResultEnum.INTERNAL_ERROR.value,
                                                 body_err=ErrorCode.INTERNAL_ERROR.value).dict(by_alias=True))

    @staticmethod
    @exter_attack
    def livemount(pid, job_id, sub_job_id):
        OracleLiveMount(pid, job_id, sub_job_id).oracle_live_mount()

    @staticmethod
    @exter_attack
    def livemount_progress(pid, job_id, sub_job_id):
        OracleLiveMount(pid, job_id, sub_job_id).live_mount_progress()

    @staticmethod
    @exter_attack
    def cancel_livemount(pid, job_id, sub_job_id):
        OracleLiveMount(pid, job_id, sub_job_id).cancel_live_mount()

    @staticmethod
    @exter_attack
    def cancel_livemount_progress(pid, job_id, sub_job_id):
        OracleLiveMount(pid, job_id, sub_job_id).cancel_live_mount_progress()

    @staticmethod
    @exter_attack
    def instant_pre_requisite(pid, job_id, sub_job_id):
        OracleInstRestore(pid, job_id, sub_job_id).instant_pre_requisite()

    @staticmethod
    @exter_attack
    def instant_pre_requisite_progress(pid, job_id, sub_job_id):
        OracleInstRestore(pid, job_id, sub_job_id).instant_pre_requisite_progress()

    @staticmethod
    @exter_attack
    def instant_restore(pid, job_id, sub_job_id):
        OracleInstRestore(pid, job_id, sub_job_id).instant_restore()

    @staticmethod
    @exter_attack
    def instant_restore_progress(pid, job_id, sub_job_id):
        OracleInstRestore(pid, job_id, sub_job_id).instant_restore_progress()

    @staticmethod
    @exter_attack
    def instant_restore_post_job(pid, job_id, sub_job_id):
        OracleInstRestore(pid, job_id, sub_job_id).instant_post_requisite()

    @staticmethod
    @exter_attack
    def instant_restore_post_job_progress(pid, job_id, sub_job_id):
        OracleInstRestore(pid, job_id, sub_job_id).instant_post_requisite_progress()

    @staticmethod
    @exter_attack
    def finalize_clear(pid, *args):
        # 将低权限用户信息放入统一变量
        add_run_user_pwd_to_env(pid, "application")
        OracleResourceService.clear_archive_log(pid)


# 各类型动作在此处定义
func_dict = {
    'CheckApplication': OracleApi.check_application,
    'QueryCluster': OracleApi.query_cluster,
    'ListApplicationResource': OracleApi.list_application,
    'ListApplicationResourceV2': OracleApi.list_application_v2,
    'OracleCheckArchiveArea': OracleApi.check_archive_area,
    'AllowBackupInLocalNode': OracleApi.allow_backup_in_local_node,
    'QueryJobPermission': OracleApi.query_job_permission,
    'CheckBackupJobType': OracleApi.check_backup_job_type,
    'BackupPrerequisite': OracleApi.backup_prerequisite,
    'BackupPrerequisiteProgress': OracleApi.backup_prerequisite_progress,
    'Backup': OracleApi.backup,
    'QueryScanRepositories': OracleApi.query_scan_repositories,
    "BackupGenSubJob": OracleApi.gen_sub_job,
    'BackupProgress': OracleApi.backup_progress,
    'BackupPostJob': OracleApi.backup_post_job,
    'BackupPostJobProgress': OracleApi.backup_post_job_progress,
    'AbortJob': OracleApi.abort_job,
    'AbortJobProgress': OracleApi.report_abort_job_progress,
    'AllowRestoreInLocalNode': OracleApi.allow_restore_in_local_node,
    'RestorePrerequisite': OracleApi.restore_prerequisite,
    'RestorePrerequisiteProgress': OracleApi.restore_prerequisite_progress,
    'RestoreGenSubJob': OracleApi.restore_gen_sub_job,
    'Restore': OracleApi.restore,
    'RestoreProgress': OracleApi.restore_progress,
    'RestorePostJob': OracleApi.restore_post_job,
    'RestorePostJobProgress': OracleApi.restore_post_job_progress,
    'Livemount': OracleApi.livemount,
    'LivemountProgress': OracleApi.livemount_progress,
    'CancelLivemount': OracleApi.cancel_livemount,
    'CancelLivemountProgress': OracleApi.cancel_livemount_progress,
    'InstantRestorePreRequisite': OracleApi.instant_pre_requisite,
    'InstantRestorePreRequisiteProgress': OracleApi.instant_pre_requisite_progress,
    'InstantRestore': OracleApi.instant_restore,
    'InstantRestoreProgress': OracleApi.instant_restore_progress,
    'InstantRestorePostJob': OracleApi.instant_restore_post_job,
    'InstantRestorePostJobProgress': OracleApi.instant_restore_post_job_progress,
    'RemoveProtect': OracleApi.remove_protect,
    'FinalizeClear': OracleApi.finalize_clear
}

if __name__ == '__main__':
    """
     功能描述：主任务执行
     参数：
     @xxx.py：argv[0] api.py python文件
     @fun_type：argv[1] 方法类型
     @pid：argv[2] 请求ID
     @job_id：argv[3] 主任务任务ID
     @sub_job_id: argv[4] 子任务ID
     例：python3 api.py fun_type pid job_id sub_job_id
    """
    for line in sys.stdin:
        SysData.SYS_STDIN = line
        break
    g_fun_type = sys.argv[1]
    g_pid = sys.argv[2]
    g_job_id = ''
    g_sub_job_id = ''
    if len(sys.argv) >= 4:
        g_job_id = sys.argv[3]
    if len(sys.argv) >= 5:
        g_sub_job_id = sys.argv[4]
    logger.debug(f'Function: {g_fun_type} start, pid: {g_pid}, job_id: {g_job_id}, sub_job_id: {g_sub_job_id}.')
    try:
        func_dict[g_fun_type](g_pid, g_job_id, g_sub_job_id)
    except KeyError:
        logger.error(f'Function: {g_fun_type} not exist.')
        sys.exit(1)
    except Exception as e:
        logger.error(f'Function: {g_fun_type}, exception: {e}.', exc_info=True)
        sys.exit(1)
    finally:
        logger.debug(f'Function: {g_fun_type} end, pid: {g_pid}, job_id: {g_job_id}, sub_job_id: {g_sub_job_id}.')
        clear(SysData.SYS_STDIN)
